package fr.mmteam.selenium.ext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URISyntaxException;

import java.net.URI;

import java.util.Collections;

import java.util.ArrayList;

import java.util.List;

/**
 * Configuration of the HTTP(S) proxy needed to access the site. 
 * Currently only basic authentication is supported.
 * 
 * @author Julien HENRY
 */
public class ProxyConfiguration {
    
    /**
     * Logger for this class.
     */
    private final Logger logger = LoggerFactory.getLogger(ProxyConfiguration.class);
    
    private String proxyHost;
    
    private int proxyPort;
    
    private String username;
    
    private String password;
    
    private List<String> nonProxyHosts = new ArrayList<String>();
    
    
    /**
     * Create a new proxy configuration without authentication.
     * @param proxyHost Proxy host name
     * @param proxyPort Proxy port
     */
    public ProxyConfiguration(String proxyHost, int proxyPort) {
        this.proxyHost = proxyHost;
        this.proxyPort = proxyPort;
    }
    
    /**
     * Create a new proxy configuration with basic authentication.
     * @param proxyHost Proxy host name
     * @param proxyPort Proxy port
     * @param username Username
     * @param password Password
     */
    public ProxyConfiguration(String proxyHost, int proxyPort, String username, String password) {
        this(proxyHost, proxyPort);
        this.username = username;
        this.password = password;
    }

    
    public String getProxyHost() {
        return proxyHost;
    }

    
    public ProxyConfiguration setProxyHost(String proxyHost) {
        this.proxyHost = proxyHost;
        return this;
    }

    
    public int getProxyPort() {
        return proxyPort;
    }

    
    public ProxyConfiguration setProxyPort(int proxyPort) {
        this.proxyPort = proxyPort;
        return this;
    }

    
    public String getUsername() {
        return username;
    }

    
    public ProxyConfiguration setUsername(String username) {
        this.username = username;
        return this;
    }

    
    public String getPassword() {
        return password;
    }

    
    public ProxyConfiguration setPassword(String password) {
        this.password = password;
        return this;
    }

    /**
     * Return an immutable list of non proxy hosts.
     *
     * @return
     */
    public List<String> getNonProxyHosts() {
        return Collections.unmodifiableList(nonProxyHosts);
    }
    
    /**
     * Add a host name that should not use proxy. Wildcard "*" prefix is supported (e.g.: *.mycompany.com)
     *
     * @param nonProxyHost
     */
    public ProxyConfiguration addNonProxyHost(String nonProxyHost) {
        nonProxyHosts.add(nonProxyHost);
        return this;
    }

    /**
     * 
     * Verify if a given URI is eligible to use the current proxy configuration
     * regarding nonProxyHosts.
     *
     * @param uriStr URI of the request
     * @return false if the URI match one of the nonProxyHosts. true otherwise.
     */    
    public boolean useProxy(String uriStr) {
        URI uri;
        try {
            uri = new URI(uriStr);
        }
        catch (URISyntaxException e) {
            logger.warn("Unable to parse request URI. Proxy will not be used", e);
            return false;
        }
        String host = uri.getHost();
        for (String nonProxyHost : nonProxyHosts) {
            if (nonProxyHost.startsWith("*")) {
                if (host.endsWith(nonProxyHost.substring(1))) {
                    return false;
                }
            }
            else {
                if (host.equals(nonProxyHost)) {
                    return false;
                }
            }
        }
        return true;
    }
    
}
